﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.ObjectMapping;
using Abp.Runtime.Caching;
using Abp.UI;
using AutoMapper.QueryableExtensions;
using FwProject.Core.Distribution;
using FwProject.Core.Restaurant;
using FwProject.Core.TypeNumber;
using FwProject.Distribution.Dto;
using FwProject.Manager;
using FwProject.Restaurant.Dto;
using FwProject.TypeNumber.Dto;
using Microsoft.AspNetCore.Mvc.Rendering;
using X.PagedList;

namespace FwProject.Restaurant
{
    [AbpAuthorize]
    public class RestaurantTypeNumberAppService : FwProjectAppServiceBase, IRestaurantTypeNumberAppService
    {
        public readonly IRepository<RestaurantTypenNumberInfo, Guid> _repositoryRestaurantTypeNumberInfo;
        public readonly IRepository<TypeNumberInfo, Guid> _repositoryTypeNumberInfo;

        public readonly IRepository<LoadCar, Guid> _repositoryLoadCar;
        private readonly RestaurantTypeNumberInfoManager _typenumberManager;
        public readonly ICacheManager _catchmanager;

        private readonly IRestaurantAppService _restaurantAppService;

        public readonly IRepository<DistributionInfo, Guid> _distributionInfoRepository;
        public readonly IRepository<DistributionInfoDetails, Guid> _distributionInfoDetailsRepository;
        public IGuidGenerator _guid { get; set; }
        public IObjectMapper _map { get; set; }
        public RestaurantTypeNumberAppService(
            IRepository<DistributionInfo, Guid> distributionInfoRepository,
            IRepository<DistributionInfoDetails, Guid> distributionInfoDetailsRepository,
            IRepository<RestaurantTypenNumberInfo, Guid> repositoryRestaurantTypeNumberInfo,
            ICacheManager catchmanager, IRepository<TypeNumberInfo, Guid> repositoryTypeNumberInfo
            , RestaurantTypeNumberInfoManager typenumberManager,
            IRestaurantAppService restaurantAppService, IRepository<LoadCar, Guid> repositoryLoadCar)
        {
            _distributionInfoRepository = distributionInfoRepository;
            _distributionInfoDetailsRepository = distributionInfoDetailsRepository;
            _repositoryLoadCar = repositoryLoadCar;
            _restaurantAppService = restaurantAppService;
            _catchmanager = catchmanager;
            _repositoryRestaurantTypeNumberInfo = repositoryRestaurantTypeNumberInfo;
            _repositoryTypeNumberInfo = repositoryTypeNumberInfo;
            _typenumberManager = typenumberManager;
            _guid = SequentialGuidGenerator.Instance;

        }

        /// <summary>
        /// 创建一个型号
        /// </summary>
        /// <returns>The create.</returns>
        /// <param name="input">Input.</param>
        public async Task<Guid> Create(RestaurantTypeNumberInput input)
        {

            var model = _map.Map<RestaurantTypenNumberInfo>(input);
            model.Id = _guid.Create();
            return await _typenumberManager.CreateRestaurantTypeNumber(model);
        }





        /// <summary>
        /// 获取一条型号信息
        /// </summary>
        /// <returns>The by identifier async.</returns>
        /// <param name="id">Identifier.</param>
        public async Task<RestaurantTypeNumberDto> GetByIdAsync(Guid id)
        {
            var model = (await GetCache).Where(O => O.Id == id).FirstOrDefault();
            return _map.Map<RestaurantTypeNumberDto>(model);

        }

        /// <summary>
        /// 根据餐厅获取该工厂下配送型号
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<RestaurantTypeNumberDto>> GetRestaurantTypeNumAsync(Guid id)
        {
            var user = await GetCurrentUserAsync();
            var model = (await GetCache).Where(o => o.Restaurantid == id && o.FactoryinfoId == user.FactoryinfoId && o.IsDefault);
            return _map.Map<List<RestaurantTypeNumberDto>>(model);

        }

        /// <summary>
        /// 获取餐厅下为没有绑定的型号
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<TypeNumberInfoDto>> GetRestaurantNotTypeNumAsync(Guid id)
        {
            var user = await GetCurrentUserAsync();
            List<TypeNumberInfoDto> list = new List<TypeNumberInfoDto>();
            var restaurantModel = await _restaurantAppService.GetByIdAsync(id);
            var model = _repositoryRestaurantTypeNumberInfo.GetAll().Where(o => o.Restaurantid == id && o.FactoryinfoId == user.FactoryinfoId).Select(o => o.TypeNumberId.Value).ToArray();
            if (model != null)
                list = _repositoryTypeNumberInfo.GetAll().Where(o => model.Contains(o.Id) == false && o.FactoryinfoId == restaurantModel.FactoryInfoId).ProjectTo<TypeNumberInfoDto>().ToList();

            return list;
        }
        /// <summary>
        /// 根据餐厅获取该工厂下配送型号
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<RestaurantTypeNumberDto>> GetRestaurantTypeNumberAsync(Guid id)
        {
            var user = await GetCurrentUserAsync();
            var model = (await GetCache).Where(o => o.Restaurantid == id && o.FactoryinfoId == user.FactoryinfoId && o.IsDefault).AsQueryable();

            return model.ProjectTo<RestaurantTypeNumberDto>().ToList();
        }
        /// <summary>
        ///配送时根据餐厅获取不是默认装车的型号
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<RestaurantTypeNumberDto>> GetAppRestaurantTypeNumAsync(Guid id)
        {
            var user = await GetCurrentUserAsync();
            var restaurantModel = await _restaurantAppService.GetByIdAsync(id);
            //if (restaurantModel.EmployeeDriverid != AbpSession.UserId.Value)
            //    throw new UserFriendlyException("该餐厅不属于你的配送范围");

            List<LoadCarTypeNumber> loadmodel = new List<LoadCarTypeNumber>();
            var loadModel = _repositoryLoadCar.GetAllIncluding(o => o.LoadingCarInfoList).Where(o => o.CarStatus == CarStatus.配送中 && o.DriverUserId == AbpSession.UserId.Value).FirstOrDefault();
            if (loadModel != null)
            {
                var m = _distributionInfoRepository.GetAllIncluding(o => o.DistributionInfoListDetails).Where(o => o.LoadCarId == loadModel.Id);
                var disIds = m.Select(o => o.Id).ToArray();
                ///得到所有的配送信息
                var list = await _distributionInfoDetailsRepository.GetAll().Where(o => disIds.Any(s => s == o.DistributionInfoId)).ToListAsync();
                var li = _map.Map<List<DistributionDetailsDto>>(list);

                if (li.Count > 0)
                {
                    loadmodel = loadModel.LoadingCarInfoList.GroupJoin((li.GroupBy(o => o.TypeNumberInfoId).Select(t => new LoadCarTypeNumber
                    {
                        TypeNumberInfoId = t.Key.Value,
                        Distributioncount = t.Sum(o => o.Distributioncount),
                        Backboxcount = t.Sum(o => o.Backboxcount)
                    }).DefaultIfEmpty()),
                      b => b.TypeNumberInfoId, k => k.TypeNumberInfoId, (b, k) => new LoadCarTypeNumber
                      {
                          TypeNumberInfoId = b.TypeNumberInfoId.Value,
                          Distributioncount = b.Countproduct - k.DefaultIfEmpty(new LoadCarTypeNumber()).FirstOrDefault().Distributioncount + k.DefaultIfEmpty(new LoadCarTypeNumber()).FirstOrDefault().Backboxcount
                      }).ToList();
                }
                else
                {

                    loadmodel = loadModel.LoadingCarInfoList.Select(o => new LoadCarTypeNumber
                    {
                        TypeNumberInfoId = o.TypeNumberInfoId.Value,
                        Distributioncount = o.Countproduct
                    }).ToList();
                }
                ////// 获取实际配送情况

            }
            var model = _map.Map<List<RestaurantTypeNumberDto>>((await GetCache).Where(o => o.Restaurantid == id && o.FactoryinfoId == user.FactoryinfoId));
            foreach (var item in model)
            {
                if (loadmodel.Where(o => o.TypeNumberInfoId == item.TypeNumberId).FirstOrDefault() != null)
                    item.LoadCarTypeNumber = loadmodel.Where(m => m.TypeNumberInfoId == item.TypeNumberId).FirstOrDefault();

            }
            return model;
        }

        /// <summary>
        /// 获取型号列表
        /// </summary>
        /// <returns>The restaurant paged list async.</returns>
        /// <param name="型号编号">Page index.</param>
        public async Task<IPagedList<RestaurantTypeNumberDto>> GetPagedListAsync(int pageIdx, int pageSize, DateTime? begindateTime, DateTime? enddatetime)
        {
            var listmodel = (await GetCache).AsQueryable();
            if (begindateTime != null)
                listmodel.Where(o => o.CreationTime >= begindateTime);

            if (enddatetime != null)
                listmodel.Where(o => o.CreationTime <= enddatetime);

            return await listmodel.ProjectTo<RestaurantTypeNumberDto>().ToPagedListAsync(pageIdx, pageSize);

        }
        /// <summary>
        /// 修改型号信息
        /// </summary>
        /// <returns>The update.</returns>
        /// <param name="id">Identifier.</param>
        /// <param name="input">Input.</param>
        public async Task Update(Guid id, RestaurantTypeNumberInput input)
        {
            var model = await _repositoryRestaurantTypeNumberInfo.GetAsync(id);
            model = _map.Map(input, model);

            await _typenumberManager.UpdateRestaurantTypeNumber(model);
        }
        /// <summary>
        /// 修改餐厅配送型号价格
        /// </summary>
        /// <param name="id"></param>
        /// <param name="price"></param>
        /// <returns></returns>
        public async Task EditPrice(Guid id, decimal price)
        {
            var model = await _repositoryRestaurantTypeNumberInfo.GetAsync(id);
            model.Price = price;
            await _typenumberManager.UpdateRestaurantTypeNumber(model);
        }

        public async Task Delete(Guid id)
        {
            var model = await _repositoryRestaurantTypeNumberInfo.GetAsync(id);
            model.IsDefault = false;
            await _typenumberManager.UpdateRestaurantTypeNumber(model);
        }

        private Task<List<RestaurantTypenNumberInfo>> GetCache
        {
            get
            {
                ICache cache = _catchmanager.GetCache(nameof(RestaurantTypenNumberInfo));
                return cache.GetAsync("list", async () => await _repositoryRestaurantTypeNumberInfo.GetAllIncluding(o => o.TypeNumberInfoModel).ToListAsync());
            }

        }

    }
}
